from ttkbootstrap.constants import *
from ttkbootstrap.scrolled import ScrolledText
from socket import *
from create_sign import *
from tkinter.filedialog import askopenfilename
from ttkbootstrap.dialogs.dialogs import Messagebox
import ttkbootstrap as ttk
import ast
import time


class ClientPage:
    def __init__(self, master=None):
        self.root = master
        self.root.minsize(800, 650)
        self.P = ttk.StringVar()
        self.RS = ttk.StringVar()
        self.filepath = ttk.StringVar()
        self.filename = None
        self.message_box_ScrolledText = None
        self.message = None
        self.rs = None
        self.public_key = None
        self.verify_page()

    def verify_page(self):
        message_box_labelframe = ttk.Labelframe(self.root, text="交互信息")
        self.message_box_ScrolledText = ScrolledText(message_box_labelframe, padding=5, height=16, autohide=True)
        self.message_box_ScrolledText.pack(fill=X, side=TOP, padx=5, pady=5)
        message_box_labelframe.pack(fill=X, padx=20, side=TOP, pady=5)

        public_key_labelframe = ttk.Labelframe(self.root, text="协同签名公钥")
        public_key_label = ttk.Label(public_key_labelframe, textvariable=self.P, wraplength=750)
        public_key_label.pack(fill=X, padx=2)
        public_key_labelframe.pack(fill=X, padx=20, side=TOP, pady=5)

        sign_rs_labelframe = ttk.Labelframe(self.root, text="协同签名值RS")
        sign_rs_label = ttk.Label(sign_rs_labelframe, textvariable=self.RS, wraplength=750)
        sign_rs_label.pack(fill=X, padx=2)
        sign_rs_labelframe.pack(fill=X, padx=20, side=TOP, pady=5)

        file_path_labelframe = ttk.Labelframe(self.root, text="签名文件路径")
        file_path_label = ttk.Label(file_path_labelframe, textvariable=self.filepath, wraplength=750)
        file_path_label.pack(fill=X, padx=2)
        file_path_labelframe.pack(fill=X, padx=20, side=TOP, pady=5)

        control_button_frame_1 = ttk.Frame(self.root)
        create_key_button = ttk.Button(control_button_frame_1, text="开启服务", command=self.connect)
        create_key_button.pack(side=LEFT, fill=X, expand=YES, padx=5, pady=5)
        create_sign_button = ttk.Button(control_button_frame_1, text="打开文件",
                                        command=self.open_file)
        create_sign_button.pack(side=LEFT, fill=X, expand=YES, padx=5, pady=5)
        save_message_button = ttk.Button(control_button_frame_1, text="验证签名",
                                         command=lambda: self.user_verify(self.rs, self.message, self.public_key))
        save_message_button.pack(side=LEFT, fill=X, expand=YES, padx=5, pady=5)
        send_sign_button = ttk.Button(control_button_frame_1, text="保存文件", command=self.save_file)
        send_sign_button.pack(side=LEFT, fill=X, expand=YES, padx=5, pady=5)
        control_button_frame_1.pack(fill=X, padx=20, pady=5, side=TOP)

    def connect(self):
        # 使用IPV4和TCP协议
        tcp_server = socket(AF_INET, SOCK_STREAM)
        # 设定ip和端口
        IP_PORT = ('', 9000)
        # 绑定链接
        tcp_server.bind(IP_PORT)
        # 设置客户端最大链接数目
        tcp_server.listen(5)
        # 允许进行连接 返回元组 参数1是返回的内容 参数2是客户端返回的地址和端口
        user_socket, clientAddr = tcp_server.accept()
        t = time.gmtime()
        temp2 = (time.strftime("%Y-%m-%d %H:%M:%S", t))
        self.message_box_ScrolledText.insert(END, temp2 + "\n")
        self.message_box_ScrolledText.insert(END, f"签名客户端{clientAddr}已连接签名验证客户端" + "\n")
        self.message_box_ScrolledText.insert(END, "\n")

        from_server_msg = user_socket.recv(1024)
        temp1 = "签名验证客户端接收到的消息为：" + from_server_msg.decode("gbk")
        t = time.gmtime()
        temp2 = (time.strftime("%Y-%m-%d %H:%M:%S", t))
        self.message_box_ScrolledText.insert(END, temp2 + "\n")
        self.message_box_ScrolledText.insert(END, temp1 + "\n")
        self.message_box_ScrolledText.insert(END, "\n")
        print("签名验证客户端接收到的消息为：" + from_server_msg.decode("gbk"))
        dict = ast.literal_eval(from_server_msg.decode("gbk"))  # 将接收到的信息强制转化为字典
        self.message = dict['message']
        self.rs = dict['rs']
        self.public_key = dict['public_key']
        self.P.set(self.public_key)
        self.RS.set(self.rs)

    def user_verify(self, sign: str, message: list, public_key: str):
        user = CryptSM2(public_key=public_key)
        user.message_to_sm3_hash(message)
        data = user.data
        print(data)
        print(sign)
        print(public_key)
        verify = user.verify(sign, data)
        if verify:
            Messagebox.ok(title='签名验证结果', message='签名验证通过，文件信息完整！')
        else:
            Messagebox.show_warning(title='签名验证结果', message='签名验证失败，文件信息可能被篡改！')
        print('verify:%s' % verify)

    def open_file(self):
        path = askopenfilename()
        if not path:
            return

        with open(path, encoding='utf-8') as f:
            dict = ast.literal_eval(f.read())

            self.message = dict['message']
            self.rs = dict['rs']
            self.public_key = dict['public_key']

            self.P.set(self.public_key)
            self.RS.set(self.rs)
            self.filepath.set(path)

    def save_file(self):  # 将明文写入当前路径
        self.filename = '明文.txt'
        with open(self.filename, 'w') as file_object:
            file_object.write(self.message[0])
        Messagebox.ok(title='保存签名', message='签名文件已经成功保存至软件相同路径!')


if __name__ == '__main__':
    root = ttk.Window("协同签名验证客户端", "minty")
    ClientPage(root)
    root.mainloop()

